package models

import (
	"encoding/json"
	"fmt"
	"log"
	"time"

	"qmp_go_push/conf"
	"qmp_go_push/utils"

	"gopkg.in/natefinch/lumberjack.v2"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

type Model struct {
	ID        uint `gorm:"primaryKey"`
	CreatedAt time.Time
	UpdatedAt time.Time
	DeletedAt gorm.DeletedAt `gorm:"index"`
	dbContext *DBContext
}

type DBContext struct {
	db       *gorm.DB `gorm:"-"`
	teamUuid string   `gorm:"-"`
	userUuid string   `gorm:"-"`
	nickname string   `gorm:"-"`
}

func NewDBContext(teamUuid, userUuid, nickname string) *DBContext {
	return &DBContext{db: db, teamUuid: teamUuid, userUuid: userUuid, nickname: nickname}
}

func (c *DBContext) GetTeamUuid() string {
	return c.teamUuid
}
func (c *DBContext) GetUserUuid() string {
	return c.userUuid
}
func (c *DBContext) GetNickname() string {
	return c.userUuid
}

type Time time.Time

func (t Time) MarshalJSON() ([]byte, error) {
	this := time.Time(t)
	format := this.Format(time.DateTime)
	if this.IsZero() {
		format = ""
	}
	return utils.StringToBytes(fmt.Sprintf("\"%v\"", format)), nil
}

var db *gorm.DB

func InitMysql() {
	dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
		conf.CONFIG.Database.User,
		conf.CONFIG.Database.Password,
		conf.CONFIG.Database.Host,
		conf.CONFIG.Database.Name)

	lumberjackLogger := &lumberjack.Logger{
		Filename:  conf.CONFIG.Log.LogSavePath + "sql.log",
		LocalTime: true,
		MaxSize:   conf.CONFIG.Log.LogMaxSize,
		MaxAge:    conf.CONFIG.Log.LogMaxAge,
	}

	var err error
	db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: logger.New(log.New(lumberjackLogger, "", log.LstdFlags), logger.Config{
			SlowThreshold:             200 * time.Millisecond,
			Colorful:                  true,
			IgnoreRecordNotFoundError: false,
			ParameterizedQueries:      false,
			LogLevel:                  logger.Info,
		}),
	})

	if err != nil {
		log.Fatal("Fatal error gorm.Open(): \n", err.Error())
	}

	sqlDB, err := db.DB()
	if err != nil {
		log.Fatal("Fatal error db.DB(): \n", err.Error())
	}

	if err = sqlDB.Ping(); err != nil {
		log.Fatal("Fatal error sqlDB.Ping(): \n", err.Error())
	}

	sqlDB.SetMaxIdleConns(10)
	sqlDB.SetMaxOpenConns(100)

	log.Println("===============初始化MYSQL配置成功===============")
	marshalIndent, _ := json.MarshalIndent(&conf.CONFIG.Database, "", "\t")
	log.Println(string(marshalIndent))
	log.Println()
	log.Println()
}

type TeamInfo struct {
	TeamUuid string
	RoleType int
	IsBan    int
	IsQuit   int
}

func GetTeamInfoByUserUuid(userUuid string) (teamInfo TeamInfo) {
	db.Table("ddm_team_info").
		Joins("INNER JOIN ddm_team_member AS tm ON tm.team_uuid = ddm_team_info.team_uuid").
		Where("tm.is_use = 1 AND tm.user_uuid = ?", userUuid).
		Select([]string{"tm.team_uuid", "tm.role_type", "tm.is_ban", "tm.quit_id"}).
		First(&teamInfo)
	return
}

type UserInfo struct {
	Phone    string
	Nickname string
	UserUuid string
}

func GetUserInfoByUserUuid(userUuid string) (userInfo UserInfo) {
	db.Table("ddm_user_info").
		Where("user_uuid = ?", userUuid).
		Select([]string{"user_uuid", "nickname", "phone"}).
		First(&userInfo)
	return
}
